package com.tang.codec;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;

import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.List;

/**
 * 自定义解码器
 *
 * @author fulin.tang
 * @since 2021/8/22
 */
public class MyDecoder extends ByteToMessageDecoder {

    private static final int BASE_LENGTH = 4;

    private final Charset charset;

    public MyDecoder() {
        this.charset = StandardCharsets.UTF_8;
    }

    public MyDecoder(Charset charset) {
        this.charset = charset;
    }

    @Override
    protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List<Object> list) throws Exception {

        // 基础长度不足则不处理
        if (byteBuf.readableBytes() < BASE_LENGTH) {
            return;
        }

        int beginIdx;

        while (true) {
            // 获取包头开始的index
            beginIdx = byteBuf.readerIndex();
            // 标记包头开始的index
            byteBuf.markReaderIndex();
            // 读到了协议的开始标志，结束while循环
            if (byteBuf.readByte() == 0x02) {
                break;
            }
            /*
            未读到包头，略过一个字节
            每次略过，一个字节，去读取，包头信息的开始标记
             */
            byteBuf.resetReaderIndex();
            byteBuf.readByte();
            /*
            当略过，一个字节之后
            数据包的长度，又变得不满足
            此时，应该结束。等待后面的数据到达
             */
            if (byteBuf.readableBytes() < BASE_LENGTH) {
                return;
            }

        }

        // 剩余长度不足可读取数量【没有内容长度位】
        int readableBytes = byteBuf.readableBytes();
        if (readableBytes <= 1) {
            byteBuf.readerIndex(beginIdx);
            return;
        }

        // 长度域占4字节，读取int
        ByteBuf buf = byteBuf.readBytes(1);
        String msgLengthStr = buf.toString(charset);
        int msgLength = Integer.parseInt(msgLengthStr);

        // 剩余长度不足可读取数量【没有结尾标识】
        readableBytes = byteBuf.readableBytes();
        if (readableBytes < msgLength + 1) {
            byteBuf.readerIndex(beginIdx);
            return;
        }

        ByteBuf msgBuf = byteBuf.readBytes(msgLength);

        byte end = byteBuf.readByte();
        if (end != 0x03) {
            byteBuf.readerIndex(beginIdx);
        }

        list.add(msgBuf.toString(charset));

    }

}
